package cn.qingyun.gis.modules.express.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

@Component
@Slf4j
public class ThreadPoolTool {

    private static int corePoolSize;
    private static int maxPoolSize;
    private static int keepAliveSeconds;
    private static int queueCapacity;
    private static Boolean enableMonitor;
    private static ThreadPoolTaskExecutor executor;

    private static AtomicBoolean startMonitor = new AtomicBoolean(false);

    /**
     * 创建自定义线程池
     *
     * @return
     */
    public static ThreadPoolTaskExecutor callerRunsPolicyExecutor() {

        return callerRunsPolicyExecutor(corePoolSize);
    }

    public static ThreadPoolTaskExecutor callerRunsPolicyExecutor(int corePoolSize) {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //核心线程池大小
        executor.setCorePoolSize(corePoolSize);
        //最大线程数
        executor.setMaxPoolSize(maxPoolSize);
        //队列容量
        executor.setQueueCapacity(queueCapacity);
        //活跃时间
        executor.setKeepAliveSeconds(keepAliveSeconds);
        //线程名字前缀
        executor.setThreadNamePrefix("SyncExecutor-");
        //交由主线程执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();

        return executor;
    }

    public static ThreadPoolTaskExecutor singletonExecutor() {
        if (executor == null) {
            synchronized (ThreadPoolTool.class) {
                if (executor == null) {
                    executor = callerRunsPolicyExecutor(corePoolSize);
                    return executor;
                } else {
                    return executor;
                }
            }
        } else {
            return executor;
        }
    }

    public static ThreadPoolTaskExecutor discardOldestPolicyExecutor() {
        return discardOldestPolicyExecutor(queueCapacity);
    }


    public static ThreadPoolTaskExecutor discardOldestPolicyExecutor(int queueCapacity) {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //核心线程池大小
        executor.setCorePoolSize(corePoolSize);
        //最大线程数
        executor.setMaxPoolSize(maxPoolSize);
        //队列容量
        executor.setQueueCapacity(queueCapacity);
        //活跃时间
        executor.setKeepAliveSeconds(keepAliveSeconds);
        //线程名字前缀
        executor.setThreadNamePrefix("SyncExecutor-");
        //交由主线程执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
        executor.initialize();

        return executor;
    }

    public static void startPrintThreadPoolInfo(ThreadPoolTaskExecutor executor) {
        if (!startMonitor.get()) {
            synchronized (ThreadPoolTool.class) {
                if (!startMonitor.get()) {
                    startMonitor.set(true);
                    new Thread(() -> {
                        try {
                            while (startMonitor.get()) {
                                TimeUnit.SECONDS.sleep(1L);
                                log.info("================  线程监控 ==> 存活线程数: " + executor.getThreadPoolExecutor().getActiveCount() + "\n" +
                                        "================  线程监控 ==> 待处理任务: " + executor.getThreadPoolExecutor().getQueue().size() + "\n" +
                                        "================  线程监控 ==> 已完成任务: " + executor.getThreadPoolExecutor().getCompletedTaskCount() + "\n");
                            }
                        } catch (InterruptedException ignored) {

                        }
                    }).start();
                }
            }
        }
    }

    public static void endPrintThreadPoolInfo() {
        startMonitor.set(false);
    }

    @Value("${qingyun.thread.core-pool-size:10}")
    public void setCorePoolSize(int corePoolSize) {
        ThreadPoolTool.corePoolSize = corePoolSize;
    }

    @Value("${qingyun.thread.max-pool-size:20}")
    public void setMaxPoolSize(int maxPoolSize) {
        ThreadPoolTool.maxPoolSize = maxPoolSize;
    }

    @Value("${qingyun.thread.keep-alive-seconds:60}")
    public void setKeepAliveSeconds(int keepAliveSeconds) {
        ThreadPoolTool.keepAliveSeconds = keepAliveSeconds;
    }

    @Value("${qingyun.thread.queue-capacity:1024}")
    public void setQueueCapacity(int queueCapacity) {
        ThreadPoolTool.queueCapacity = queueCapacity;
    }


    @Value("${qingyun.thread.enable-monitor:false}")
    public void setEnableMonitor(Boolean enableMonitor) {
        ThreadPoolTool.enableMonitor = enableMonitor;
    }
}
